In order to develop software, it is important to have debugging tools to find bugs or errors in the software. One of the important features of a debugger is the ability to set break points on an instruction and get control of the computer program to examine its state when the flow of control of the program reaches the break point. Typical computer systems or peripheral debug diagnostic systems, for example, logic analyzers, implement break points by using individual registers. A register is a memory element storing a plurality of bits. Each bit in the register can be a logical 0 or a logical 1, as is common in digital computer systems. Thus, the break point is defined by a bit pattern of logical 0's and logical 1's called a break point code, which is stored in the register. In general, a debugger is expected to support multiple break points since there might be multiple points of interest to the user. To implement break points, the user first specifies an address (A) to the debugger where the program must break in order to activate the break point. The debugger then replaces the software instruction at address (A) with a break instruction.
Subsequently, during the execution of the computer program, if the break instruction is executed, control is transferred to the debugger which either prints a message or waits for user input. This transfer of control allows a computer operator to then scrutinize various contents of the computer system to examine if the computer system is in a proper state at the time of recognition, that is, at the break point. When the program execution needs to be continued, the break point instruction is replaced with the actual instruction which had originally been present in the computer program. This approach works well when the program to be debugged exists in a memory location which can be written to by the user. However, in embedded systems, the computer program usually resides in read-only memory (ROM), which cannot be written to by the user. Thus, the above approach of replacing the instruction at the break point with a break point instruction is not possible.
One prior art approach of debugging programs in ROM is to always single step the program, as known in the art, and compare the address of the instruction to be executed with a previously-specified list of break points set by the user. Using this approach, any number of break points can be supported in the debugging program without the need for any extra hardware support. However, this single-step approach is rarely used because it is extremely slow. The execution time of the program in a debugging mode is several orders of magnitude slower than the actual program which makes for a very unpleasant debugging experience.
A second alternate prior art approach to debug computer programs that are present in ROM is to provide additional hardware to support break points in ROM. This approach has been used by embedded processors like the ARM, Lucent 1600, Lucent 16000, TI C54X, etc. embedded processors.
Reference is now made to FIG. 1 which depicts an example of the second prior art approach to debug computer programs that are present in ROM by providing additional hardware to support break points in ROM. In the prior art, a hardware debugging support module 5 consists of a break point address list 7 and a comparator 6 as shown in FIG. 1. The output of break point address list 7 is connected to comparator 6 within hardware debugging support module 5. Comparator 6 taps into address bus 14 which transfers information between processor 12 and memory 10 of the computer system. A predetermined user defined list of break point addresses is stored in break point address list 7. When hardware debugging support module 5 is in operation, comparator 6 compares the actual condition existing on address bus 14, i.e., the address being passed between processor 12 and memory 10, with the list of addresses that are stored in break point address list 7. When comparator 6 finds a match between a signal on address bus 14 and an address stored in break point address list 7, comparator 6 signals that a break point has been recognized, and hardware debugging support module 5 interrupts processor 12 and transfers control to the debugger. Since the comparison performed by comparator 6 must be done at the speed of processor 12 and the silicon resources needed for storing the list of break point addresses in break point address list 7 is large, prior art processors limit break points to an extremely small and finite number. Generally, only one breakpoint address can be loaded into one of the registers at any one time. Thus, to implement a plurality of break points requires a plurality of break point registers which increases the complexity and cost of the hardware. Generally, break point address list 7 is implemented using one or two registers, thereby limiting the debugger to the use of only one or two break points. Thus, it is desirable to provide for a new technique that allows for the placement of a greater number of break points in ROM with a finite amount of hardware resources.